﻿using System;
using System.Diagnostics;
using System.Reflection;
using Hallenberg.Core;
using Hallenberg.SmartClient.Interfaces;

namespace Hallenberg.SmartClient
{
    public class BaseSmartClientApplication : ISmartClientApplication
    {
        public event EventHandler<EventArgs<IServiceLocator>> OnRegisterInternalServices;
        private WorkItemController m_WorkItem;

        public WorkItemController WorkItem
        {
            get
            {
                if (m_WorkItem == null)
                {
                    m_WorkItem = new WorkItemController();
                    WorkItemInitialized();
                }

                return m_WorkItem;
            }
        }

        public virtual void WorkItemInitialized()
        {
        }

        public virtual void RegisterAssembly(Assembly assembly)
        {
            #region Asserting assumptions

            Debug.Assert(assembly != null);
            if (assembly == null)
            {
                throw new ArgumentNullException("assembly");
            }

            #endregion

            WorkItem.AddRegisteredAssembly(assembly);
        }

        protected virtual void RegisterInternalServices()
        {
            if (OnRegisterInternalServices != null)
            {
                OnRegisterInternalServices(this, new EventArgs<IServiceLocator>(this.WorkItem.Services));
            }
        }

        public virtual void ApplicationStart()
        {
            RegisterInternalServices();

            foreach (Assembly assembly in WorkItem.GetRegisteredAssemblies())
            {
                foreach (Type assemblyType in assembly.GetTypes())
                {
                    WorkItem.HandleType(assemblyType);
                }
            }

            foreach(IBaseModule module in WorkItem.Modules.AllModules)
            {
                module.Initialize();
            }
        }

        public virtual string ResolveRelativePath(string relativePath)
        {
            Debug.Assert(!string.IsNullOrEmpty(relativePath));
            if (string.IsNullOrEmpty(relativePath))
            {
                throw new ArgumentNullException("relativePath");
            }

            return relativePath;
        }
    }
}
